/////precompiled////////
#include "precompiled.h"
////////////////////////


#include "svl_TTimer.h"

using namespace svl;

////////////////////////////////////////////////////////////////////////////////
///**************************************************************************///
////////////////////////////////////////////////////////////////////////////////

namespace Igor{

HANDLE       TTimer::s_TimerQueue = NULL;
unsigned int TTimer::s_TimerCount = 0;

//////////

void CALLBACK TTimer::f_TimerCallBack (PVOID _pTimer, BOOLEAN _flag) {
    TTimer* ptimer = static_cast<TTimer*>(_pTimer);
    if (ptimer != NULL)
        ptimer->TTimer_Tick();
    return;
}

///==========================================================================///

TTimer::TTimer (DWORD _start, DWORD _period) {
    if (s_TimerQueue == NULL)
        s_TimerQueue = ::CreateTimerQueue();

    ::CreateTimerQueueTimer(
        &m_Handle, s_TimerQueue, f_TimerCallBack, 
        (PVOID)this, _start, _period, 0
    );                                                   
    s_TimerCount++;
}                                       

///==========================================================================///

TTimer::~TTimer (void) {
    ::DeleteTimerQueueTimer(s_TimerQueue, m_Handle, INVALID_HANDLE_VALUE);
	s_TimerCount--;
    if (0 == s_TimerCount) {
        ::DeleteTimerQueueEx(s_TimerQueue, INVALID_HANDLE_VALUE);
		s_TimerQueue = NULL;
    }
}

///==========================================================================///

void TTimer::setTimeOut (DWORD _start, DWORD _period) {
    if (NULL != m_Handle && NULL != s_TimerQueue)
        ::ChangeTimerQueueTimer(s_TimerQueue, m_Handle, _start, _period);
    return;
}

};

////////////////////////////////////////////////////////////////////////////////
///**************************************************************************///
////////////////////////////////////////////////////////////////////////////////
// TTimer //////////////////////////////////////////////////////

svl::TTimer::TLink svl::TTimer::links[10] =
{
  { (::TIMERPROC)svl::TTimer::TimerProc0,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc1,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc2,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc3,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc4,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc5,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc6,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc7,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc8,NULL },
  { (::TIMERPROC)svl::TTimer::TimerProc9,NULL }
};

//
svl::TTimer::TTimer(DWORD _start, DWORD _period)
: start(_start)
, En(false)
{
  	if( !_start )
		En = true;
	else
		startTickCount = ::GetTickCount();

	idTimer = ::SetTimer(NULL,0,_period,New(this));
}

//
svl::TTimer::~TTimer()
{
  ::KillTimer(NULL,idTimer); Delete(this);
}

//
svl::TTimer *svl::TTimer::Get(::TIMERPROC Proc)
{
  for (int N = 0; N < 10; N++)
  {
    if (links[N].Proc == Proc) { return links[N].Timer;}
  }
  svl::TExcept("svl::TTimer::Get").Throw(); return NULL;
}

//
::TIMERPROC svl::TTimer::New(TTimer *V)
{
  for (int N = 0; N < 10; N++)
  {
    if (!links[N].Timer) { links[N].Timer = V; return links[N].Proc;}
  }
  svl::TExcept("svl::TTimer::New").Throw(); return NULL;
}

//
void svl::TTimer::Delete(TTimer *V)
{
  for (int N = 0; N < 10; N++)
  {
    if (links[N].Timer == V) { links[N].Timer = NULL; return;}
  }
  svl::TExcept("svl::TTimer::Delete").Throw();
}

//
void svl::TTimer::Tick(){
	if( !En )
		if( ::GetTickCount() - startTickCount > start )
			En = true;
		else
			return;
	
	TTimer_Tick();
}